<?php
///
namespace lxsphp\Store\Pdo\Command;

///
use lxsphp\App;

/**
 * 表示一个数据表实例。
 * // 不是一个真正的Active Record实现，更象是一个数据表提供外部使用的视图
 *
 * @version $Id: Table.php 194 2014-07-18 06:22:47Z linsir123 $
 * @package lxsphp\Store\Pdo\Command
 */
class Table
{
	/**
	 * 使用的数据源索引
	 *
	 * @var string
	 */
	public $dsnIndex = "lxsphp";

	/**
	 * 对应的数据库表名
	 *
	 * @var string
	 */
	public $table = "";

	/**
	 * @var \lxsphp\Store\Pdo\Pdo
	 */
	public $pdo;

	/**
	 * @var Command
	 */
	public $cmd;

	/**
	 * @var \PDOStatement
	 */
	public $sth;

	/**
	 * 构造函数
	 */
	public function __construct()
	{
		///
		$this->pdo = App::getPdo($this->dsnIndex);

		///
		$this->cmd = new Command($this->pdo);
		$this->cmd->from($this->table);
	}

	/**
	 * @param array $params
	 *
	 * @return mixed
	 */
	public function getRow($params = array())
	{
		///
		$this->cmd->limit(1);

		///
		return $this->_queryInternal('fetch', \PDO::FETCH_ASSOC, $params);
	}

	/**
	 * @param array $params
	 *
	 * @return mixed
	 */
	public function getAll($params = array())
	{
		///
		return $this->_queryInternal('fetchAll', \PDO::FETCH_ASSOC, $params);
	}

	/**
	 * @param array $params
	 *
	 * @return mixed
	 */
	public function getColumn($params = array())
	{
		///
		return $this->_queryInternal('fetchAll', array(\PDO::FETCH_COLUMN, 0), $params);
	}

	/**
	 * @param array $params
	 *
	 * @return mixed
	 */
	public function getVar($params = array())
	{
		///
		$this->cmd->limit(1);

		///
		$result = $this->_queryInternal('fetchColumn', 0, $params);
		if (is_resource($result) && get_resource_type($result) === 'stream')
			return stream_get_contents($result);
		else
			return $result;
	}

	/**
	 * 插入
	 *
	 * @param array $columns
	 *
	 * @return int
	 */
	public function insert($columns)
	{
		///
		$this->cmd->insert($this->table, $columns);

		return $this->execute();
	}

	/**
	 * 更新
	 *
	 * @param mixed $columns
	 * @param mixed $conditions
	 * @param array $params
	 *
	 * @return int
	 */
	public function update($columns, $conditions = '', $params = array())
	{
		///
		$this->cmd->update($this->table, $columns, $conditions, $params);

		return $this->execute();
	}

	/**
	 * 删除
	 *
	 * @param mixed $conditions
	 * @param array $params
	 *
	 * @return int
	 */
	public function delete($conditions = '', $params = array())
	{
		///
		$this->cmd->delete($this->table, $conditions);

		return $this->execute($params);
	}

	/**
	 * 绑定参数
	 *
	 * @param mixed $name
	 * @param mixed $value
	 *
	 * @return Table
	 */
	public function bindParam($name, &$value)
	{
		///
		$this->prepare();
		$this->sth->bindParam($name, $value);

		return $this;
	}

	/**
	 * 准备SQL
	 *
	 * @throws Exception
	 */
	public function prepare()
	{
		///
		if ($this->sth == null) {
			try {
				///
				App::$I->getDebugger()->timerStart();

				$sql = $this->cmd->getText();
				$this->sth = $this->pdo->getPdo()->prepare($sql);

				///
				App::$I->getDebugger()->log($sql);

			} catch (\Exception $e) {

				///
				throw new Exception('[TableBase] ...');
			}
		}
	}

	/**
	 * 执行命令
	 *
	 * @param array $params
	 *
	 * @throws Exception
	 * @return null
	 */
	public function execute($params = array())
	{
		try {
			$this->prepare();
			$params = array_merge($this->cmd->params, $params);

			///
			if ($params === array())
				$this->sth->execute();
			else
				$this->sth->execute($params);

			///
			$n = $this->sth->rowCount();
			$this->_reset();

			return $n;

		} catch (\Exception $e) {

			///
			throw new Exception('[TableBase] ...');
		}
	}

	/**
	 * 获取数据
	 *
	 * @param string $method
	 * @param mixed $mode
	 * @param array $params
	 *
	 * @throws Exception
	 * @return mixed
	 */
	protected function _queryInternal($method, $mode, $params = array())
	{
		///
		try {
			$this->prepare();
			$params = array_merge($this->cmd->params, $params);

			///
			if ($params === array())
				$this->sth->execute();
			else
				$this->sth->execute($params);

			///
			$mode = (array)$mode;
			call_user_func_array(array($this->sth, 'setFetchMode'), $mode);
			$result = $this->sth->$method();
			$this->sth->closeCursor();
			$this->_reset();

			return $result;

		} catch (\Exception $e) {

			///
			throw new Exception('[TableBase] ...');
		}
	}

	/**
	 * 重置
	 */
	protected function _reset()
	{
		///
		$this->sth = null;

		///
		$this->cmd->from($this->table);
		$this->cmd->reset();
	}
}
